/**
 * CONCENTRÉ // Xml entreprise grade framework 
 *
 * @fileoverview	Concentré
 * @author			Sébastien CRAMATTE <scramatte@zensoluciones.com> 
 * @version			$Release$ - $Revision: 161 $
 * 
 * Please visit these sites for details :
 * http://concentre.zensoluciones.com 
 * http://code.google.com/p/concentre-xforms
 * 
 * License: GPL v2 or later (http://www.gnu.org/licenses/gpl.html)
 *
 * Copyright (C) 2004-2006 Sébastien Cramatte <scramatte(at)zensoluciones(dot)com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

function assert(condition, message) {
  	if (!condition) {
    	throw new Exception('Concentré: '+ Concentre.Factory.i18n.translate(message));
  	}	
};
	


Concentre = {
	options: {
		basePath: null,
		xmlDocument: null
	},
	objectsById: {},
	objectsHashTable: {},
	modulesHashTable: {},	
	modules: [],
	initialize: function (options) {

		this.setOptions(options);
		
		//try {
		
			if ( this.options.basePath == null) {
				this.options.basePath = this.getBasePath();
  			}
  			
  			assert(this.options.basePath,'Invalid base path.');
	  	
	  		Concentre.htmlHead = document.getElementsByTagName('head')[0];
	    	Concentre.htmlBody = document.getElementsByTagName('body')[0];
	    	
	    	var lang = Concentre.Factory.i18n.getlanguage();
	 		Concentre.Factory.i18n.load(this.options.basePath+'i18n/'+lang+'.xml');
			
			
	        if ( this.xmlDocument == null) { 
	        	this.xmlDocument = Concentre.Factory.Xml.loadURL(window.location.href);
			}
			
			assert(this.xmlDocument,'Invalid XML document.');
	  		
	  	    if ( this.xsltDocument == null) { 
	    			this.xsltDocument = Concentre.Factory.Xslt.getStylesheet(this.options.basePath+'xsl/concentre.xsl');
			}
			
			assert(this.xsltDocument,'Invalid XSLT stylesheet.');
	  			  		
			this.xsltDocument.setParameter(null, 'concentre-path', this.options.basePath );
		
			var expr = new XPath('namespace::*');
			this.namespaceNodes = expr(this.xmlDocument.documentElement);
		
			
			for (var i=0; i < this.namespaceNodes.length ; i++) {
				var ns = this.namespaceNodes[i];
			   	QName._namespaces[ns.prefix] = ns.namespaceURI;	
			}
		
			var expr = new XPath('xhtml:body');
			var body = expr(this.xmlDocument.documentElement, QName)[0];
			
			if (document.implementation && document.implementation.createDocument) {			
				resultDoc = document.implementation.createDocument("", "", null);
			} else {
				resultDoc = window.document;
			}
			
			var fragment = this.xsltDocument.transformToFragment(body, resultDoc);
			Concentre.htmlBody.innerHTML = fragment.firstChild.innerHTML;

			this.modules.unshift(Concentre.XForms);

					
			for (var i=this.modules.length; --i>=0; ) {
				this.modules[i].initialize(this);
			}
			
			this.bind(Concentre.htmlBody);
	
			for (var i=this.modules.length; --i>=0; ) {			
				this.modules[i].start();
			}
		
		/*
		} catch (e) {
			alert(e);
		}
		*/
	},
	
	getBasePath: function() {
			var scriptElements = document.getElementsByTagName("script");
 	  		for (var i = scriptElements.length; --i>=0; ) {
		    	var source = scriptElements[i].getAttribute("src");
	    		if (source != null && source.match(/^(.*\/)?concentre((-c)?\.js(\.gz|\.php)?)$/)) {
	    			return RegExp.$1;
	    			break;
	    		}
	  		}
	},
	
	setOptions: function(options) {
	
		if (!options instanceof Object) return;
	
		for (var o in options) {
			this.options[o] = options[o];
		}
	},
	
	bind: function(node) {
			
			for (var n = node.firstChild; n!=null; n = n.nextSibling) {
			if (n.nodeType==1) {
			  var ns = n.getAttribute('concentre');

			  if (ns) {
					var mod = Concentre.modulesHashTable[ ns.substr(1,ns.lastIndexOf('}')-1) ];
			  		var a = {};
					
					if (n.className=='concentre-xforms-action') {
						for (var i = n.attributes.length; --i>=0; ) {
					 			var attr = n.attributes[i];
					 			if (attr.name.match(/^xmlns?(\:.+)/)) continue;
					 			a[QName.toHash(attr.name)]=attr.value;
						}
					
					}
					
					if (!Concentre.objectsHashTable[ ns ]) {
						console.log(ns);
						throw new Exception(ns);
					}
					
					var c = new Concentre.objectsHashTable[ ns ](n,a, arguments[1]);
					mod.bind(n, c, arguments[2], arguments[3]);
						
				} else {
					this.bind(n);
				}
			}
		}	      
	}
};


Concentre.Factory = {};

Concentre.Class = function(superclass, overrides) {
  
  var F = function () { 
		if (arguments.length>0) {
			this.initialize.apply(this, arguments);
		} 
  };
  
  F.prototype             = new superclass();
  F.prototype.constructor = F;
  F.prototype.superclass  = superclass.prototype;

  if (overrides) {
  	for (var i in overrides) {
		F.prototype[i] = overrides[i];
  	}
  }
  
  return F;
};




Exception =  Concentre.Class( Object , {
		initialize: function(message, cause) {
			this.message = message;
			this.cause = cause;
		},
		
		toString: function() {
			var message = this.message;
  
  			if (message == "[object Error]") {
      			var message = "";

     			for (var i in err) {
        			message += i + ": " + err[i] + "\n";
      			}
      		}
      		
      	 	if (this.cause != null) {
  		 		message += "\nCause: " + this.cause;
  			}
  
  
  			return message;
  		}	
	
	});






